import random
from typing import List, Tuple, Set
from enum import Enum

class Difficulty(Enum):
    BEGINNER = "beginner"
    INTERMEDIATE = "intermediate"
    EXPERT = "expert"

DIFFICULTY_SETTINGS = {
    Difficulty.BEGINNER: {"rows": 9, "cols": 9, "mines": 10},
    Difficulty.INTERMEDIATE: {"rows": 16, "cols": 16, "mines": 40},
    Difficulty.EXPERT: {"rows": 16, "cols": 30, "mines": 99}
}

class Cell:
    def __init__(self, x: int, y: int):
        self.x = x
        self.y = y
        self.is_mine = False
        self.is_revealed = False
        self.is_flagged = False
        self.neighbor_mines = 0

class GameLogic:
    def __init__(self, difficulty: Difficulty = Difficulty.BEGINNER):
        self.set_difficulty(difficulty)
        self.initialize_grid()

    def set_difficulty(self, difficulty: Difficulty):
        """设置游戏难度"""
        settings = DIFFICULTY_SETTINGS[difficulty]
        self.rows = settings["rows"]
        self.cols = settings["cols"]
        self.num_mines = settings["mines"]
        self.current_difficulty = difficulty
        self.game_over = False
        self.first_click = True
        self.flags_left = self.num_mines
        self.grid: List[List[Cell]] = []
        self.initialize_grid()

    def initialize_grid(self):
        """初始化游戏网格"""
        self.grid = [[Cell(x, y) for y in range(self.cols)] for x in range(self.rows)]
        self.game_over = False
        self.first_click = True
        self.flags_left = self.num_mines

    def place_mines(self, first_x: int, first_y: int):
        """放置地雷，确保第一次点击的位置及其周围没有地雷"""
        safe_cells = set()
        for dx in [-1, 0, 1]:
            for dy in [-1, 0, 1]:
                new_x, new_y = first_x + dx, first_y + dy
                if 0 <= new_x < self.rows and 0 <= new_y < self.cols:
                    safe_cells.add((new_x, new_y))

        all_positions = [(x, y) for x in range(self.rows) for y in range(self.cols)
                        if (x, y) not in safe_cells]
        mine_positions = random.sample(all_positions, self.num_mines)

        for x, y in mine_positions:
            self.grid[x][y].is_mine = True

        self._calculate_neighbor_mines()

    def _calculate_neighbor_mines(self):
        """计算每个非地雷格子周围的地雷数量"""
        for x in range(self.rows):
            for y in range(self.cols):
                if not self.grid[x][y].is_mine:
                    self.grid[x][y].neighbor_mines = self._count_neighbor_mines(x, y)

    def _count_neighbor_mines(self, x: int, y: int) -> int:
        """计算指定位置周围的地雷数量"""
        count = 0
        for dx in [-1, 0, 1]:
            for dy in [-1, 0, 1]:
                new_x, new_y = x + dx, y + dy
                if (0 <= new_x < self.rows and 0 <= new_y < self.cols and
                        self.grid[new_x][new_y].is_mine):
                    count += 1
        return count

    def reveal_cell(self, x: int, y: int) -> Set[Tuple[int, int, int]]:
        """揭示一个格子，返回所有需要更新的格子集合，每个元素为 (x, y, neighbor_mines)"""
        if not (0 <= x < self.rows and 0 <= y < self.cols):
            return set()

        cell = self.grid[x][y]
        if cell.is_revealed or cell.is_flagged:
            return set()

        revealed_cells = set()
        cell.is_revealed = True

        if cell.neighbor_mines == 0 and not cell.is_mine:
            # 如果是空格子，递归揭示周围的格子
            revealed_cells.add((x, y, 0))
            for dx in [-1, 0, 1]:
                for dy in [-1, 0, 1]:
                    new_x, new_y = x + dx, y + dy
                    if (0 <= new_x < self.rows and 0 <= new_y < self.cols):
                        revealed_cells.update(self.reveal_cell(new_x, new_y))
        else:
            revealed_cells.add((x, y, cell.neighbor_mines))

        return revealed_cells

    def toggle_flag(self, x: int, y: int) -> bool:
        """切换旗子状态，返回是否成功切换"""
        if not (0 <= x < self.rows and 0 <= y < self.cols):
            return False

        cell = self.grid[x][y]
        if cell.is_revealed:
            return False

        if cell.is_flagged:
            cell.is_flagged = False
            self.flags_left += 1
            return True
        elif self.flags_left > 0:
            cell.is_flagged = True
            self.flags_left -= 1
            return True

        return False

    def check_win(self) -> bool:
        """检查是否获胜"""
        for row in self.grid:
            for cell in row:
                if not cell.is_mine and not cell.is_revealed:
                    return False
        return True

    def get_all_mines(self) -> Set[Tuple[int, int]]:
        """获取所有地雷的位置"""
        mines = set()
        for x in range(self.rows):
            for y in range(self.cols):
                if self.grid[x][y].is_mine:
                    mines.add((x, y))
        return mines 